/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	File:		GlbNet.cpp			*/
/********************************************************/

#include "GlbNet.h"

namespace GlbNet
{

CGlbNet::CGlbNet()
{
	m_iSocket = GLB_FAILURE;
}

CGlbNet::~CGlbNet()
{
	m_iSocket = GLB_FAILURE;
}

int CGlbNet::GlbNetOpen(int iDom, int iType)
{
	m_iSocket = socket(iDom, iType, 0);
	if (m_iSocket < 0) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

void CGlbNet::GlbNetClose()
{
	if (m_iSocket > 0) {
		close(m_iSocket);
		m_iSocket = GLB_FAILURE;
	}

	return;
}

int CGlbNet::GlbNetGetSocket()
{
	return m_iSocket;
}

void CGlbNet::GlbNetSetSocket(int iSocket)
{
	m_iSocket = iSocket;
}

char* CGlbNet::GlbNetUrl(char* pszUrl)
{
	while('\0' != *pszUrl && ':' != *pszUrl) pszUrl ++;
	*pszUrl ++ = '\0';

	return '\0' != *pszUrl ? pszUrl : NULL;
}

bool CGlbNet::GlbNetOkUrl(char* pszUrl)
{
	char* pszPort = NULL;
	char szUrl[GLB_URL] = { 0 };

	strncpy(szUrl, pszUrl, GLB_URL);
	pszPort = CGlbNet::GlbNetUrl(szUrl);

	return NULL != pszPort ? GlbNetOkHost(szUrl) && GlbNetOkPort(pszPort) : false;
}

bool CGlbNet::GlbNetOkHost(char* pszHost)
{
	char* pszCur = pszHost;

	while (NULL != pszCur && atoi(pszCur) < 0xff) NULL != (pszCur = strchr(pszCur, 0x2e)) ? pszCur += 1 : NULL;

	return NULL == pszCur;
}

bool CGlbNet::GlbNetOkPort(char* pszPort)
{
	UINT uiPort = atoi(pszPort);

	return uiPort <= 0xffff ? GlbNetOkPort((USHORT)uiPort) : false;
}

bool CGlbNet::GlbNetOkPort(USHORT usPort)
{
	return usPort > 0;
}

int CGlbNet::GlbNetBind(char* pszUrl)
{
	char* pszPort = NULL;
	int iReturn = GLB_SUCCESS;
	struct sockaddr_in stAddr;

	if (NULL != (pszPort = CGlbNet::GlbNetUrl(pszUrl))) {
		stAddr.sin_family = AF_INET;
		stAddr.sin_port = htons(atoi(pszPort));
		stAddr.sin_addr.s_addr = inet_addr(pszUrl);
		iReturn = bind(m_iSocket, (struct sockaddr*)&stAddr, sizeof(struct sockaddr_in));
	}
	else {
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

int CGlbNet::GlbNetBind(USHORT usPort)
{
	struct sockaddr_in stAddr;

	stAddr.sin_family = AF_INET;
	stAddr.sin_port = htons(usPort);
	stAddr.sin_addr.s_addr = htonl(INADDR_ANY);

	return bind(m_iSocket, (struct sockaddr*)&stAddr, sizeof(struct sockaddr_in));
}

int CGlbNet::GlbNetBind(void* pAddr, int iAddr)
{
	return bind(m_iSocket, (struct sockaddr*)pAddr, iAddr);
}

int CGlbNet::GlbNetBind(struct sockaddr_in* pstAddr)
{
	return bind(m_iSocket, (struct sockaddr*)pstAddr, sizeof(struct sockaddr_in));
}

int CGlbNet::GlbNetBind(struct sockaddr_un* pstAddr)
{
	return bind(m_iSocket, (struct sockaddr*)pstAddr, sizeof(struct sockaddr_un));
}

int CGlbNet::GlbNetLimit(UINT uiTotal)
{
	struct rlimit stLimit;

	memset(&stLimit, '\0', sizeof(struct rlimit));
	stLimit.rlim_max = stLimit.rlim_cur = uiTotal;

	if (GLB_FAILURE == setrlimit(RLIMIT_NOFILE, &stLimit)) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

int CGlbNet::GlbNetSetBlock()
{
	if (GLB_FAILURE == fcntl(m_iSocket, F_SETFL, fcntl(m_iSocket, F_GETFL, 0) | ~O_NONBLOCK)) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

int CGlbNet::GlbNetSetNonBlock()
{
	if (GLB_FAILURE == fcntl(m_iSocket, F_SETFL, fcntl(m_iSocket, F_GETFL, 0) | O_NONBLOCK)) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

int CGlbNet::GlbNetSetReuseAddr()
{
	int iOn = 1;

	if (GLB_FAILURE == setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR, &iOn, sizeof(iOn))) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

int CGlbNet::GlbNetSetSndBuf(UINT uiSize)
{
	if (GLB_FAILURE == setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, &uiSize, sizeof(uiSize))) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

int CGlbNet::GlbNetSetRcvBuf(UINT uiSize)
{
	if (GLB_FAILURE == setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, &uiSize, sizeof(uiSize))) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

void CGlbNet::GlbNetSetTimeOut(int iSec, int iUsec)
{
	struct timeval stTime;

	stTime.tv_sec = iSec;
	stTime.tv_usec = iUsec;

	if (GLB_FAILURE == setsockopt(m_iSocket, SOL_SOCKET, SO_SNDTIMEO, &stTime, sizeof(stTime))) {
		GLB_ERROR("%s\n", strerror(errno));
	}

	if (GLB_FAILURE == setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, &stTime, sizeof(stTime))) {
		GLB_ERROR("%s\n", strerror(errno));
	}

	return;
}

} /* GlbNet */
